#include "axi_can_drv.h"
#include "can_sys.h"
#include "can_common.h"
#include "axis_fifo_drv.h"
#include "xintc_drv.h"
#include "xcan.h"
#include "sleep.h"
#include "xutils.h"

static can_drv_t can_drv[AXI_CAN_DRV_MAX];
XGpio Gpio;

static uint8_t intc_init_status;
static uint8_t buffer_config_receive[CAN_CONFIG_FRAME_SIZE_MAX];

uint32_t Axi_fifo_init_addresses[] =
{
	0X44A00000,
	0X44A10000,
	0X44A20000,
	0X44A30000,
	0X44A40000,
	0X44A50000
};

static uint8_t can_drv_id[AXI_CAN_DRV_MAX] = {
		axi_can_drv_id0,
		axi_can_drv_id1,
		axi_can_drv_id2,
		axi_can_drv_id3,
		axi_can_drv_id4,
		axi_can_drv_id5
};
static uint8_t can_intc_drv_id[AXI_CAN_DRV_MAX] = {
		axi_can_drv_intc_id0,
		axi_can_drv_intc_id1,
		axi_can_drv_intc_id2,
		axi_can_drv_intc_id3,
		axi_can_drv_intc_id4,
		axi_can_drv_intc_id5
};
static uint32_t can_status_base_address[AXI_CAN_DRV_MAX] = {
		can_status_frame_base_address0,
		can_status_frame_base_address1,
		can_status_frame_base_address2,
		can_status_frame_base_address3,
		can_status_frame_base_address4,
		can_status_frame_base_address5
};
static uint32_t can_fifo_base_address[AXI_CAN_DRV_MAX] = {
		can_axis_fifo_base_address0,
		can_axis_fifo_base_address1,
		can_axis_fifo_base_address2,
		can_axis_fifo_base_address3,
		can_axis_fifo_base_address4,
		can_axis_fifo_base_address5
};

static void axi_can_drv_info_init(can_drv_t *drv, int drv_id, int chn_id, int drv_intc_id, uintptr_t address, uintptr_t fifo_base_address)
{
    memset(drv, 0x0, sizeof(can_drv_t));
    drv->can_id = drv_id;
    drv->can_chn_id = chn_id;
    drv->intc_id = drv_intc_id;
    drv->baud = 500000;
    drv->status_phy_addr = address;
    drv->response_phy_addr = address + CAN_RESPONSE_FRAME_OFFSET_START;
    drv->axis_fifo_base_address = fifo_base_address;
    drv->rxframe_phy_addr = can_rxframe_base_address + (chn_id * CAN_RXFRAME_ADDR_OFFSET_MAX);
    CAN_DBG(CAN_DBG_DEBUG,"can drv id:%d response_phy_addr:0x%x \r\n", drv_id, drv->response_phy_addr);
}


static void axi_can_drv_init(void)
{
	int i;
	int Status;
	for(i = 0; i < AXI_CAN_DRV_MAX; i++) {
		axi_can_drv_info_init(&can_drv[i], can_drv_id[i], i, can_intc_drv_id[i], can_status_base_address[i], can_fifo_base_address[i]);
		if(i > 3){
			axis_fifo_reset(can_drv[i].axis_fifo_base_address);
			continue;
		}
		Status = axi_can_init(&can_drv[i]);
		if(Status != 0){
			//CAN_DBG(CAN_DBG_ERROR,"can drv id:%d init error \r\n", i);
			can_drv[i].init_flag = 1;
		} else {
			if(can_drv[i].rb == NULL){
				CAN_DBG(CAN_DBG_ERROR,"chn:%d rb init error  \r\n", i);
			}
			if(!intc_init_status){
				Status = xintc_drv_connect(can_drv[i].intc_id, (Xil_ExceptionHandler)XCan_IntrHandler,&can_drv[i]);
				if(Status != 0){
					/*
					 * 这个地方将标志去掉，因为这个地方初始化失败，只会影响接收外部can，但是不影响发送数据给外部can
					 * */
					//can_drv[i].init_flag = 1;
					CAN_DBG(CAN_DBG_ERROR,"can drv id:%d intc init error \r\n", i);
				}
			}
		}
	}
}
//static int axi_gpio_drv_init(void)
//{
//    int Status;
//
//    // 初始化GPIO设备
//    Status = XGpio_Initialize(&Gpio, XPAR_GPIO_0_DEVICE_ID);
//    if (Status != XST_SUCCESS)
//    {
//        CAN_DBG(CAN_DBG_ERROR, "Gpio Initialization Failed\r\n");
//        return XST_FAILURE;
//    }
//
//
//    // 配置GPIO方向：根据掩码设置输入/输出
//    // GPIO_DR_DATA的位为1表示输入，0表示输出
//    XGpio_SetDataDirection(&Gpio, GPIO_DR_INIT, GPIO_DR_DATA);
//    XGpio_SetDataDirection(&Gpio, GPIO_DR_INIT_1,0);
//    XGpio_WriteReg(0x40000000,0x08,1);
//    xil_printf("Successfully GPIO init\r\n");
//    return XST_SUCCESS;
//}

/*
 * 这个不关心返回值，配置不对，采用默认的进行通信
 *
 * */
static void parse_and_init_can(can_config_frame_t *frame)
{
	can_drv_t *pcan_drv_t;
	uint32_t expected_checksum;

    if (frame->head != axi_can_data_frame_head) {
    	CAN_DBG(CAN_DBG_ERROR,"config head error:0x%08x ,\r\n",frame->head);
        return ;
    }

    expected_checksum = calculate_xor_checksum((uint8_t *)frame, sizeof(can_config_frame_t)-4);
    if ((frame->xor_checksum != expected_checksum) ||(frame->ch_id > AXI_CAN_DRV_MAX)  ||(DIR_HOST_TO_DEVICE != frame->direction)||(0 != frame->type))
    {
    	CAN_DBG(CAN_DBG_ERROR,"config error checksum:%d ch_id:%d direction:%d type:%d \r\n",frame->xor_checksum, frame->ch_id, frame->direction, frame->type);
    	return ;
    }

    pcan_drv_t = &can_drv[frame->ch_id];
    if(pcan_drv_t->init_flag){
    	CAN_DBG(CAN_DBG_ERROR,"chn id:%d no init \r\n", frame->ch_id);
    	return ;
    }

	axi_can_config(pcan_drv_t, frame->baud_rate);
	/*
	 * 目前协议只有正常和回环
	 * */
	if(frame->mode){
		axi_can_set_mode(pcan_drv_t, XCAN_MODE_NORMAL);
		CAN_DBG(CAN_DBG_DEBUG,"CAN MODE SET SUCCESSFUL XCAN_MODE_NORMAL \r\n");
	}else {
		axi_can_set_mode(pcan_drv_t, XCAN_MODE_LOOPBACK);
		CAN_DBG(CAN_DBG_DEBUG,"CAN MODE SET SUCCESSFUL XCAN_MODE_LOOPBACK \r\n" );
	}

    return ;
}

uint32_t swap_endian_32bit_1(uint32_t value)
{
    return ((value & 0xFF000000) >> 24) |
           ((value & 0x00FF0000) >> 8)  |
           ((value & 0x0000FF00) << 8)  |
           ((value & 0x000000FF) << 24);
}


static void can_send(can_drv_t *pcan_drv, can_request_frame_t *request_frame, can_status_frame_t  *status_frame, uint32_t count)
{
	int i, ret;
	u32 Can_TxFrame[4] = {0,0,0,0};

	ret = 0;
	for(i = 0; i < count; i++)
	{
		status_frame[i].type = CMD_DEVICE_STATUS;


		//* 如果 can请求包不为NULL，表示要发送can包，否则就只是对can状态返回包进行信息更正
		//if((request_frame != NULL) && (0 == pcan_drv->init_flag)){
		if((request_frame != NULL))
		{
			//Can_TxFrame[0] = request_frame[i].idr;

//	        int IdExtension= 0;
//	        unsigned int idr = request_frame[i].idr;
//
//			bool is_extended_frame = (request_frame[i].idr & XCAN_IDR_IDE_MASK) != 0;
//			if(is_extended_frame)
//			{
//				IdExtension = 1;
////				//idr = swap_endian_32bit_1(idr);
////				unsigned short h_data = (idr & 0xFFFF0000) >> 16;
////				unsigned short l_data = (idr & 0x0000FFFF);
////				idr = (l_data<<16) | h_data ;
//				Can_TxFrame[0] = XCan_CreateIdValue(idr, 0, IdExtension, 0, 0);
//				//Can_TxFrame[0] =idr;
//				Can_TxFrame[1] = XCan_CreateDlcValue(request_frame[i].drcr);
//				Can_TxFrame[2] = request_frame[i].dw1r;
//				Can_TxFrame[3] = request_frame[i].dw2r;
//			}
//			else
//			{
//				//Can_TxFrame[0] = request_frame[i].idr;
//				Can_TxFrame[0] = XCan_CreateIdValue(idr, 0, IdExtension, 0, 0);
//				Can_TxFrame[1] = XCan_CreateDlcValue(request_frame[i].drcr);
//				Can_TxFrame[2] = request_frame[i].dw1r;
//				Can_TxFrame[3] = request_frame[i].dw2r;
//			}

//
//			Can_TxFrame[0] = XCan_CreateIdValue(idr, 0, IdExtension, 0, 0);
			Can_TxFrame[0] =request_frame[i].idr;
			Can_TxFrame[1] = XCan_CreateDlcValue(request_frame[i].drcr);
			Can_TxFrame[2] = request_frame[i].dw1r;
			Can_TxFrame[3] = request_frame[i].dw2r;

			 //* 发送can数据
			CAN_DBG(CAN_DBG_DEBUG,"request_frame[i].idr:0x%08x \r\n",request_frame[i].idr );


			while (XCan_IsTxFifoFull(&pcan_drv->can) == TRUE);
			ret = XCan_Send(&pcan_drv->can, Can_TxFrame);
			uint32_t low_bits = Xil_In32(AXI_TIMER_OPEN_LOW);
			uint32_t high_bits = Xil_In32(AXI_TIMER_OPEN_HIGH);
			CAN_DBG(CAN_DBG_DEBUG,"low_bits:0x%08x,high_bits:0x%08x \r\n",low_bits,high_bits  );
			status_frame[i].timestamp = ((uint64_t)high_bits << 32) | (uint64_t)low_bits;
			CAN_DBG(CAN_DBG_DEBUG,"status_frame[i].timestamp:0x%016llx \r\n",status_frame[i].timestamp);

			//* 发送失败，进行相关的can状态返回包进行信息更正
			if(ret != XST_SUCCESS)
			{
				CAN_DBG(CAN_DBG_DEBUG,"CAN SEND NOT SUCCESSFUL \r\n");
				status_frame[i].xor_states = 2;
				if(count > 1)
				{
					status_frame[i].type = CMD_CAN_SINGLE_ERROR;
				} else
				{
					status_frame[i].type = CMD_CAN_MULTI_ERROR;
				}
			}
			else
			{
				//CAN_DBG(CAN_DBG_DEBUG,"CAN SEND SUCCESSFUL \r\n");
				status_frame[i].xor_states = 0;
			}
		}
		else
		{
			//*进行相关的can状态返回包进行信息更正
			status_frame[i].xor_states = 1;
			if(count > 1)
			{
				status_frame[i].type = CMD_CAN_SINGLE_ERROR;
			}
			else
			{
				status_frame[i].type = CMD_CAN_MULTI_ERROR;
			}
		}
		status_frame[i].xor_checksum = calculate_xor_checksum((void*)&status_frame[i], sizeof(can_status_frame_t) - 4);
	}
}


static void can_send_status_farme(void)
{
	int i,j;
	can_drv_t *pcan_drv;
	can_frame_info_t frame_info;
	uint32_t offset, rb_count;
	can_response_frame_t response_frame;
	can_axis_fifo_frame_t axis_fifo_frame;
	u32 rxFrame[4];

	memset(&response_frame, 0x0, sizeof(response_frame));

	for(i = 0; i < AXI_CAN_DRV_MAX; i++){
		pcan_drv = &can_drv[i];

		if(pcan_drv->rb == NULL){
			continue;
		}

		if(!ringbuffer_is_empty(pcan_drv->rb)){
			rb_count=ringbuffer_len(pcan_drv->rb);
			//CAN_DBG(CAN_DBG_DEBUG,"chn%d rb rb_count:%d \r\n", i, rb_count);

//			if(rb_count >= CAN_SEND_RESPONSE_FRAME_RB_COUNT_MAX){
//				rb_count = CAN_SEND_RESPONSE_FRAME_RB_COUNT_MAX;
//			}

			offset = pcan_drv->response_frame_offset;
			if(pcan_drv->response_frame_offset % CAN_RESPONSE_FRAME_OFFSET){
				offset = ((pcan_drv->response_frame_offset / CAN_RESPONSE_FRAME_OFFSET) + 1) * CAN_RESPONSE_FRAME_OFFSET;
			}

			if(offset + (rb_count * CAN_ONE_STATUS_FRAME_SIZE) >= CAN_RESPONSE_FRAME_OFFSET_START){
				offset = 0;
			}

			for(j = 0; j < rb_count; j++){

				ringbuffer_get(pcan_drv->rb, (uint8_t *)&frame_info, sizeof(can_frame_info_t));
				memcpy((void *)rxFrame, (void*)(pcan_drv->rxframe_phy_addr + (frame_info.offset * CAN_FIFO_ONE_FRAME_SIZE)),  CAN_FIFO_ONE_FRAME_SIZE);

		    	response_frame.head = axi_can_data_frame_head;
		    	response_frame.direction = DIR_DEVICE_TO_HOST;
		    	response_frame.type = CMD_DEVICE_NORMAL;
		    	response_frame.length =CAN_ONE_STATUS_FRAME_SIZE;
		    	response_frame.ch_id = pcan_drv->can_chn_id;
		        response_frame.idr =rxFrame[0];
		        response_frame.drcr=rxFrame[1] >> 28;
		        response_frame.dw1r=rxFrame[2];
		        response_frame.dw2r=rxFrame[3];
		        response_frame.states = frame_info.states;
		        response_frame.timestamp=Xil_In32(0x40000000);;
		        response_frame.total_count = rb_count;
		        response_frame.ch_count = j;
		        response_frame.xor_checksum=calculate_xor_checksum((void*)&response_frame, sizeof(can_response_frame_t) - 4);

		        memcpy((can_response_frame_t *)(pcan_drv->response_phy_addr + offset + (j * sizeof(can_response_frame_t))), &response_frame, sizeof(response_frame));
			}

			pcan_drv->response_frame_offset = offset + (rb_count * sizeof(can_response_frame_t));
			axis_fifo_frame.head=axi_can_fifo_frame_head;
			axis_fifo_frame.direction= DIR_DEVICE_TO_HOST;
			axis_fifo_frame.count=pcan_drv->fifo_frame_count;
	        axis_fifo_frame.pack_ddr_base=pcan_drv->response_phy_addr + offset;
	        axis_fifo_frame.pkt_len=rb_count*CAN_ONE_STATUS_FRAME_SIZE;

	        axis_fifo_write_data(pcan_drv->axis_fifo_base_address, (unsigned char*)&axis_fifo_frame, sizeof(can_axis_fifo_frame_t));
	        pcan_drv->response_frame_offset = offset + (rb_count * sizeof(can_response_frame_t));
		}
	}
}

#if 0
static void can_send_request_frame(can_drv_t *pcan_drv, uint32_t pack_ddr_base, uint32_t pkt_len)
{
	can_axis_fifo_frame_t axis_fifo_frame;
	can_request_frame_t *request_frame;
	can_status_frame_t  *status_frame;
	uint32_t rem, count, done, offset;
	uint32_t calculated_xor,packets_count, packets_sum;
	uint32_t frame_error,request_len;

	request_len = pkt_len;

	/*
	 * 只处理整包数据
	 * */
	if(pkt_len % sizeof(can_request_frame_t)){
		request_len = (pkt_len / sizeof(can_request_frame_t)) * sizeof(can_request_frame_t);
	}

	/*
	 * 获取本次状态反馈包的ddr地址的偏移
	 * */
	offset = pcan_drv->status_frame_offset;
	if(pcan_drv->status_frame_offset % CAN_CMD_STATUS_FRAME_OFFSET){
		offset = ((pcan_drv->status_frame_offset / CAN_CMD_STATUS_FRAME_OFFSET) + 1) * CAN_CMD_STATUS_FRAME_OFFSET;
	}


	/*
	 * 因为 arm--->上位机的ddr被会分成 状态反馈包的ddr + can外部的数据的ddr，
	 * 因此当偏移到尾部的时候，要回头
	 * */
	if((offset + request_len) >= CAN_RESPONSE_FRAME_OFFSET_START){
		//CAN_DBG(CAN_DBG_DEBUG,"#chn:%d offset:%d-%d pkt_len:(%d) ###\r\n", pcan_drv->can_chn_id, pcan_drv->status_frame_offset, offset, pkt_len);
		offset = 0;
	}

	/*
	 * 上位机-->arm的请求包 和 arm-->上位机的状态反馈包都是 48字节且格式基本是一致的，只是其中个别字节有区别。而且每个请求包
	 * 都有与之对应的状态反馈包，因此可以直接进行拷贝，只是修改其中的不同部分。
	 * */
	memcpy((void *)(pcan_drv->status_phy_addr + offset), (void *)pack_ddr_base, request_len);


	done = 0;
	count = sizeof(can_request_frame_t);

	packets_count = 0;
	frame_error = 0;

	/*
	 * 因为ddr中的请求包会有很多个，因此拆分成一个一个请求包进行解析
	 * */
	//CAN_DBG(CAN_DBG_DEBUG,"id:%d base:0x%x offset:%d len:%d count:%d \r\n",pcan_drv->can_chn_id ,pack_ddr_base, offset, pkt_len, (request_len / count));
	//sleep(1);
	while(1){
		can_send_status_farme();

		rem = request_len - done;

		/*
		 * 表示处理完成了
		 * */
		if(rem == 0) {
			if(packets_count != 0){
				can_send(pcan_drv, NULL,(can_status_frame_t *)(pcan_drv->status_phy_addr + offset), (request_len / count));
			}

			break;
		}

		request_frame = (can_request_frame_t *)(pack_ddr_base + done);
		status_frame = (can_status_frame_t *)(pcan_drv->status_phy_addr + offset + done);

		calculated_xor = calculate_xor_checksum((void*)request_frame, sizeof(can_request_frame_t) - 4);

		/*
		 * 表示本包出错，记录相关的状态
		 * */
		//xil_printf("calculated_xor:0x%08x request_frame->xor_checksum: 0x%08x\r\n",calculated_xor,request_frame->xor_checksum);
		if ((calculated_xor != request_frame->xor_checksum) || (request_frame->direction != 0) || (request_frame->head != axi_can_data_frame_head)){
		//if ((request_frame->direction != 0) || (request_frame->head != axi_can_data_frame_head)){
			frame_error = 1;
			status_frame->xor_states = 0;
		} else {
			status_frame->xor_states = 1;
		}

		packets_sum = request_frame->packets_sum;
		/*
		 * 包计数不对，则包出错，记录状态
		 * */
		if(request_frame->packets_no != packets_count){
			frame_error = 1;
			//CAN_DBG(CAN_DBG_DEBUG," packets_count %d != %d  \r\n", packets_count, request_frame->packets_no);
		}

		/*	表示是整个包组中的最后一包了，进行相关处理
		 * 	负责就包计数+1
		 * */
		if(((packets_count + 1) == packets_sum)){
			/*
			 * 如果没有错误包存在，则进行can包发送，有错报就包进行can包发送
			 * */
			if(!frame_error){
				can_send(pcan_drv, (can_request_frame_t *)(pack_ddr_base),
						(can_status_frame_t *)(pcan_drv->status_phy_addr + offset), (request_len / count));
			} else {
				can_send(pcan_drv, NULL,
						(can_status_frame_t *)(pcan_drv->status_phy_addr + offset), (request_len / count));
			}

			packets_count = 0;
			frame_error = 0;
		} else {
			packets_count = request_frame->packets_no + 1;
		}

		done += count;
	}

	/*
	 * 所有的请求包都处理完成了，将状态反馈包发送给上位机
	 * */
	while(1){
		/*
		 * 状态反馈包发送给上位机也包括can中断来的，的简答的进行处理一下(暂时没有用到 mutex)，防止竞争fifo资源
		 * */
		axis_fifo_frame.head=axi_can_fifo_frame_head;
		axis_fifo_frame.direction=DIR_DEVICE_TO_HOST;
		axis_fifo_frame.count=pcan_drv->fifo_frame_count;
		axis_fifo_frame.pack_ddr_base=pcan_drv->status_phy_addr + offset;
		axis_fifo_frame.pkt_len= request_len;

		axis_fifo_write_data(pcan_drv->axis_fifo_base_address, (unsigned char*)&axis_fifo_frame, sizeof(can_axis_fifo_frame_t));

		pcan_drv->status_frame_offset = offset + pkt_len;
		pcan_drv->fifo_frame_count += 1;
		break;
	}
}
#else

static void can_send_request_frame(can_drv_t *pcan_drv, uint32_t pack_ddr_base, uint32_t pkt_len)
{
	can_axis_fifo_frame_t axis_fifo_frame;
	can_request_frame_t *request_frame;
	can_status_frame_t  *status_frame;
	uint32_t rem, count, done, offset;

	uint32_t calculated_xor,packets_count, packets_sum;
	uint32_t frame_error,request_len;

	uint8_t *frame_buffer;


	request_len = pkt_len;

	frame_buffer = (uint8_t *)malloc(pkt_len);
	if(frame_buffer == NULL){
		CAN_DBG(CAN_DBG_ERROR,"malloc size %d error \r\n", pkt_len);
		return ;
	}

	if(pkt_len % sizeof(can_request_frame_t)){
		request_len = (pkt_len / sizeof(can_request_frame_t)) * sizeof(can_request_frame_t);
	}


	offset = pcan_drv->status_frame_offset;
	if(pcan_drv->status_frame_offset % CAN_CMD_STATUS_FRAME_OFFSET){
		offset = ((pcan_drv->status_frame_offset / CAN_CMD_STATUS_FRAME_OFFSET) + 1) * CAN_CMD_STATUS_FRAME_OFFSET;
	}



	if((offset + request_len) >= CAN_RESPONSE_FRAME_OFFSET_START){
		//CAN_DBG(CAN_DBG_DEBUG,"#chn:%d offset:%d-%d pkt_len:(%d) ###\r\n", pcan_drv->can_chn_id, pcan_drv->status_frame_offset, offset, pkt_len);
		offset = 0;
	}


	memcpy((void *)(frame_buffer), (void *)pack_ddr_base, request_len);

	done = 0;
	count = sizeof(can_request_frame_t);

	packets_count = 0;
	frame_error = 0;
	bool first_recv=true;
	uint32_t pre_frm_cnt=0;

	uint32_t continus_cnts= 0;

	uint32_t bag_cnts = request_len / sizeof(can_request_frame_t);
	while(1)
	{
		can_send_status_farme();

		rem = request_len - done;

		if(rem == 0)
		{

			if(bag_cnts==(continus_cnts +1))
			{
				if(!frame_error){
					can_send(pcan_drv, (can_request_frame_t *)(frame_buffer),
							(can_status_frame_t *)(frame_buffer), (request_len / count));
				} else {
					can_send(pcan_drv, NULL,
							(can_status_frame_t *)(frame_buffer), (request_len / count));
				}
			}
			//if(packets_count != 0)
			//{
			//	//CAN_DBG(CAN_DBG_DEBUG," #### packets_count: %d  \r\n", packets_count);
			//	can_send(pcan_drv, NULL,(can_status_frame_t *)(frame_buffer), (request_len / count));
			//}
			break;
		}

		request_frame = (can_request_frame_t *)(frame_buffer + done);
		status_frame = (can_status_frame_t *)(frame_buffer + done);

		calculated_xor = calculate_xor_checksum((void*)request_frame, sizeof(can_request_frame_t) - 4);


		if ((calculated_xor != request_frame->xor_checksum) || (request_frame->direction != 0) || (request_frame->head != axi_can_data_frame_head)){
		//if ((request_frame->direction != 0) || (request_frame->head != axi_can_data_frame_head)){
			frame_error = 1;
		}

		packets_sum = request_frame->packets_sum;

		done += count;
		if(first_recv)
		{
			pre_frm_cnt= request_frame->packets_no;
			first_recv=false;
			continue;
		}
		u_int32_t cur_frm_cnt = request_frame->packets_no;
		if(cur_frm_cnt - pre_frm_cnt != 1)
		{
			frame_error = 1;
			CAN_DBG(CAN_DBG_DEBUG," cur_frm_cnt %d != pre_frm_cnt:%d  \r\n", cur_frm_cnt, pre_frm_cnt);
		}
		else
		{
			pre_frm_cnt =  cur_frm_cnt;
			continus_cnts++;
		}


		/*
		 * ���������ԣ������������¼״̬
		 * */
//		if(request_frame->packets_no != packets_count)
//		{
//			frame_error = 1;
//			CAN_DBG(CAN_DBG_DEBUG," packets_count %d != %d  \r\n", packets_count, request_frame->packets_no);
//		}
//
//		if(((packets_count + 1) == packets_sum))
//		{
//			/*
//			 *
//			 * */
//			//CAN_DBG(CAN_DBG_DEBUG," #### frame_error: %d  \r\n", frame_error);
//			if(!frame_error){
//				can_send(pcan_drv, (can_request_frame_t *)(frame_buffer),
//						(can_status_frame_t *)(frame_buffer), (request_len / count));
//			} else {
//				can_send(pcan_drv, NULL,
//						(can_status_frame_t *)(frame_buffer), (request_len / count));
//			}
//
//			packets_count = 0;
//			frame_error = 0;
//		} else {
//			packets_count = request_frame->packets_no + 1;
//		}
//

	}

	memcpy((void *)(pcan_drv->status_phy_addr + offset), (void *)frame_buffer, request_len);

	while(1){
		/*
		 * ״̬
		 * */
		axis_fifo_frame.head=axi_can_fifo_frame_head;
		axis_fifo_frame.direction=DIR_DEVICE_TO_HOST;
		axis_fifo_frame.count=pcan_drv->fifo_frame_count;
		axis_fifo_frame.pack_ddr_base=pcan_drv->status_phy_addr + offset;
		axis_fifo_frame.pkt_len= request_len;

		axis_fifo_write_data(pcan_drv->axis_fifo_base_address, (unsigned char*)&axis_fifo_frame, sizeof(can_axis_fifo_frame_t));

		pcan_drv->status_frame_offset = offset + pkt_len;
		//CAN_DBG(CAN_DBG_DEBUG," #### pcan_drv->status_frame_offset: %d  \r\n", pcan_drv->status_frame_offset);
		pcan_drv->fifo_frame_count += 1;
		break;
	}

	free(frame_buffer);
	//sleep(1);
}

#endif

void axi_can_frame_transfer(void)
{
	can_drv_t *pcan_drv;
	int i, ret,data_len;
	can_axis_fifo_frame_t axis_fifo_frame;
	int send_cnt = 0;
	//axis_fifo_reset(CONFIG_FIFO_BASEADDRESS);
	Xil_Out32(AXI_TIMER_OPEN_T,0X01);
	uint32_t open_time = Xil_In32(AXI_TIMER_OPEN_T);
	CAN_DBG(CAN_DBG_DEBUG ,"read open_time:0x%08x \r\n",open_time);



	while(1)
	{
		/*
		 * 每100ms左右判断一下是否有空余的包没有发送，有则发送
		 * */
		/*
		 * 读取配置包，进行CAN相关的设置
		 *
		 * */
	//	data_len = axis_fifo_read_data_len(CONFIG_FIFO_BASEADDRESS);
		for(int i=0;i<AXI_CAN_DRV_MAX;i++)
		{
			data_len = axis_fifo_read_data_len(Axi_fifo_init_addresses[i]);
			if(data_len > 0)
			{
				ret = axis_fifo_read_data(Axi_fifo_init_addresses[i], buffer_config_receive, data_len);
				parse_and_init_can((can_config_frame_t *)buffer_config_receive );
				axis_fifo_reset(Axi_fifo_init_addresses[i]);
				if(ret != data_len)
				{
					CAN_DBG(CAN_DBG_ERROR,"read fifo config frame error,(%d !=%d) \r\n",data_len,ret);
				}
			}
		}

		/*
		 * 根据设备进行can指令的发送，其采用的方式为:
		 * 从fifo中读取一帧数据，然后根据数据帧的地址和长度，获取can的数据进行发送
		 * 多设备的话，也是一样的，只不过将流程拉大了，变成
		 * can0 第1帧 --->can1 第1帧 ---->can0 第2帧 --->can1 第2帧 ... ...
		 * */

		for(i = 0; i < AXI_CAN_DRV_MAX; i++)
		{
			//CAN_DBG(CAN_DBG_DEBUG,"read GPIO data %d \r\n", gpio_data);

			pcan_drv = &can_drv[i];
			can_send_status_farme();

			/*
			 *读取长度，并进行判断
			 * */
			data_len = axis_fifo_read_data_len(pcan_drv->axis_fifo_base_address);
			/*
			 * 如果长度不足一帧，不进行发送
			 * */
			if(data_len >= sizeof(can_axis_fifo_frame_t))
			{
				/*
				 *如果数据不足一帧，表示数据有问题，则复位fifo，不进行发送
				 * */
				ret = axis_fifo_read_data(pcan_drv->axis_fifo_base_address, (unsigned char*)&axis_fifo_frame, sizeof(can_axis_fifo_frame_t));
				if(ret != sizeof(can_axis_fifo_frame_t))
				{
					CAN_DBG(CAN_DBG_ERROR,"read can config  error (%d != %d) \r\n", ret, sizeof(can_axis_fifo_frame_t));
					//axis_fifo_reset(pcan_drv->axis_fifo_base_address);
					continue;
				}
				if(axis_fifo_frame.direction==0x3)
				{
					//表示进入单机模拟状态
					CAN_DBG(CAN_DBG_DEBUG,"START ALONG MODE \n\r");
					pcan_drv->alonge_start = 1;
					while(1)
					{
						for(uint8_t offset = 0; offset < ALONG_SUM_OFFSET; offset += ALONG_OFFSET)
						{
							uint8_t* src_addr = (uint8_t*)(axis_fifo_frame.pack_ddr_base+offset);
							CAN_DBG(CAN_DBG_DEBUG,"DDR_BASE_OFFSET:0X%08X,DDR_BASE_ADDR: 0X%08X , OFFSET:0X%08X \n\r",src_addr,axis_fifo_frame.pack_ddr_base,offset);
							uint8_t temp_buffer[sizeof(ALONG_DataPacket)];
							memcpy(temp_buffer, src_addr, sizeof(temp_buffer));
							ALONG_DataPacket *frame_t =( ALONG_DataPacket *)temp_buffer;
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->head: 0x%08x\r\n",frame_t->head);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->direction: 0x%08x\r\n",frame_t->direction);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->type: 0x%08x\r\n",frame_t->type);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->length: 0x%08x\r\n",frame_t->length);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->channel_id: 0x%08x\r\n",frame_t->channel_id);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->total_count: 0x%08x\r\n",frame_t->total_count);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->channel_count: 0x%08x\r\n",frame_t->channel_count);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->packet_type: 0x%08x\r\n",frame_t->packet_type);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->can_id: 0x%08x\r\n",frame_t->can_id);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->data_type: 0x%08x\r\n",frame_t->data_type);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->rcv_len: 0x%08x\r\n",frame_t->rcv_len);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->send_len: 0x%08x\r\n",frame_t->send_len);
							CAN_DBG(CAN_DBG_DEBUG,"frame_t->reserved: 0x%08x\r\n",frame_t->reserved);
							if(frame_t->head != axi_can_data_frame_head || frame_t->type != ALONG_TYPE )
							{
								CAN_DBG(CAN_DBG_DEBUG,"Along_Stand.head: 0x%08x, Along_Stand.type:0x%02x\r\n",frame_t->head, frame_t->type);
								break ;
							}
							if(frame_t->can_id ==  rxFrame_along[0] && frame_t->data_type ==  rxFrame_along[2])
							{
								CAN_DBG(CAN_DBG_DEBUG,"FRAME_CANID:0x%08x,rxFrame_along[0]:0x%08x,frame_t->data_type:0x%08x,rxFrame_along[2]:0x%08x\r\n",frame_t->can_id,rxFrame_along[0],frame_t->data_type,rxFrame_along[2]);

								if(send_cnt == (frame_t->rcv_len - 1)/8)
								{
									send_cnt = 0;
									for(int i=0;i<frame_t->send_len;i+=CAN_FIFO_ONE_FRAME_SIZE)
									{
										for(int j=0 ;j<CAN_FIFO_ONE_FRAME_SIZE;j+=4)
										{
											u32 Can_TxFrame_t[4];
											Can_TxFrame_t[j]=frame_t->send_data[j*4];
											while(XCan_IsTxFifoFull(&pcan_drv->can) == TRUE);
											ret = XCan_Send(&pcan_drv->can,Can_TxFrame_t);
											if(ret != XST_SUCCESS)
											{
												CAN_DBG(CAN_DBG_DEBUG,"CAN SEND NOT SUCCESSFUL \r\n");
											}
											pcan_drv->alonge_start = 0;

										}
									}
									break;

								}
								else
								{
									//等第二次中断来
									pcan_drv->alonge_start = 1;
									while(pcan_drv->alonge_start == 1)
									{
										send_cnt++;
									}

								}
							}
						}
					}
				}
				/*
				 * 进行数据的发送以及状态包的发送
				 * */
				//CAN_DBG(CAN_DBG_DEBUG,"### pack_ddr_base:0x%x pkt_len:%d ## \r\n", axis_fifo_frame.pack_ddr_base, axis_fifo_frame.pkt_len);
				can_send_request_frame(pcan_drv, axis_fifo_frame.pack_ddr_base, axis_fifo_frame.pkt_len);
			}
		}
	}
}

void axi_can_system_init(void)
{
	int Status;

	/* 初始化中断控制器 */
	intc_init_status = 0;

    Status = xintc_drv_init();
	if(Status){
		CAN_DBG(CAN_DBG_ERROR,"intc drv init error \r\n");
		intc_init_status = 1;
	}
//	if (axi_gpio_drv_init() != XST_SUCCESS) {
//	    // 处理初始化失败的情况
//		CAN_DBG(CAN_DBG_ERROR,"intc drv_GPIO init error \r\n");
//	}

	/* 初始化CAN 设备 */
    axi_can_drv_init();

    /* 启用中断 */
    xintc_drv_start();
}
